package org.ielts.action.base;

import static com.yifeng.struts2.RequestParameters.*;
import static com.yifeng.struts2.ResultParameters.*;
import static com.yifeng.struts2.ResultConstants.*;
import static com.yifeng.struts2.ActionUtils.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.hibernate.NonUniqueResultException;
import org.ielts.action.BaseAction;
import org.ielts.domain.base.Classroom;
import org.ielts.domain.base.CourseType;
import org.ielts.domain.base.Lesson;
import org.ielts.domain.base.Teaching;
import org.ielts.domain.log.OrderLessonLog;
import org.ielts.domain.report.LessonQuery;
import org.ielts.domain.report.LessonRemoveReport;
import org.ielts.domain.report.TeacherBlankLessonReport;
import org.ielts.domain.report.TeacherLessonReport;
import org.ielts.domain.security.Role;
import org.ielts.domain.security.User;
import org.ielts.profile.IeltsProfile;
import org.ielts.service.ClassroomService;
import org.ielts.service.CourseTypeService;
import org.ielts.service.LessonService;
import org.ielts.service.OrderLessonService;
import org.ielts.service.TeacherService;
import org.ielts.service.TeachingService;
import org.ielts.service.security.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;

import com.yifeng.ProfileContext;
import com.yifeng.TimePair;
import com.yifeng.domain.Day;
import com.yifeng.domain.Time;
import com.yifeng.dto.DtoTable;
import com.yifeng.dto.FormRow;
import com.yifeng.dto.IDtoRow;
import com.yifeng.dto.UploadFile;
import com.yifeng.modules.annotations.Operation;
import com.yifeng.poi.ExcelUtils;
import com.yifeng.profile.Profile;
import com.yifeng.struts2.RequestParameters;
import com.yifeng.struts2.action.FormAction;
import com.yifeng.utils.JsonResultBuilder;
import com.yifeng.utils.PageUtils;
import com.yifeng.utils.ParseUtils;
import com.yifeng.web.Pagers;
import com.yifeng.web.Paginations;

public class LessonAction extends BaseAction {

	@Autowired
	LessonService lessonService;

	@Autowired
	ClassroomService classroomService;

	@Autowired
	TeacherService teacherService;

	@Autowired
	CourseTypeService courseTypeService;

	@Autowired
	TeachingService teachingService;

	boolean moring = false;

	public boolean isMorning(Date date) {
		if (!moring) {

			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			if (calendar.get(Calendar.HOUR_OF_DAY) < 12) {
				moring = true;
				return true;
			}
		}

		return false;
	}

	boolean afternoon = false;

	public boolean isAfternoon(Date date) {
		if (!afternoon) {

			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			if (calendar.get(Calendar.HOUR_OF_DAY) >= 12) {
				afternoon = true;
				return true;
			}
		}

		return false;
	}

	boolean evening = false;

	public boolean isEvening(Date date) {
		if (!evening) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			if (calendar.get(Calendar.HOUR_OF_DAY) >= 18) {
				evening = true;
				return true;
			}
		}

		return false;
	}

	@Operation(result = FILL)
	public String modifyLesson() {
		String id = form.readString("id");

		Lesson lesson = lessonService.findOne(id);
		put("lesson", lesson);

		Iterable<User> teachers = teacherService.findAll();
		put("teachers", teachers);

		Iterable<Classroom> classrooms = classroomService.findAll();
		put("classrooms", classrooms);

		Iterable<CourseType> courseTypes = courseTypeService.findAll();
		put("courseTypes", courseTypes);

		return FILL;
	}

	@Operation(result = FILL)
	public String viewLesson() {
		String id = form.readString("id");

		Lesson lesson = lessonService.findOne(id);
		put("lesson", lesson);

		Iterable<User> teachers = teacherService.findAll();
		put("teachers", teachers);

		Iterable<Classroom> classrooms = classroomService.findAll();
		put("classrooms", classrooms);

		Iterable<CourseType> courseTypes = courseTypeService.findAll();
		put("courseTypes", courseTypes);

		return FILL;
	}

	@Operation(result = JSON)
	public String doModifyLesson() throws ParseException {
		String id = form.readString("id");

		String day = form.readString("date");
		String beginTimeStr = form.readString("beginTime");
		String endTimeStr = form.readString("endTime");

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");

		Date beginTime = simpleDateFormat.parse(day + " " + beginTimeStr);
		Date endTime = simpleDateFormat.parse(day + " " + endTimeStr);

		String name = form.readString("name");

		String[] teacherIds = form.readStrings("teacher");
		String[] teachingBeginTimes = form.readStrings("teachingBeginTime");
		String[] teachingEndTimes = form.readStrings("teachingEndTime");

		String classroom = form.readString("classroom");
		String courseType = form.readString("courseType");

		int no = valueReader.name("no").defaultValue(0).intValue();

		ArrayList<Teaching> teachings = new ArrayList<Teaching>();
		for (int i = 0; i < teacherIds.length - 1; i++) {
			Teaching teaching = new Teaching();

			User teacher = new User();
			teacher.setId(teacherIds[i]);

			teaching.setTeacher(teacher);

			Date teachingBeginTime = beginTime;

			try {
				String timeStr = teachingBeginTimes[i];
				if (StringUtils.isNotBlank(timeStr) && !"00:00".equals(timeStr)) {
					teachingBeginTime = simpleDateFormat.parse(day + " " + timeStr);
				}
			} catch (ParseException ex) {

			}

			Date teachingEndTime = endTime;
			try {
				String timeStr = teachingEndTimes[i];
				if (StringUtils.isNotBlank(timeStr) && !"00:00".equals(timeStr)) {
					teachingEndTime = simpleDateFormat.parse(day + " " + timeStr);
				}
			} catch (ParseException ex) {

			}

			teaching.setBeginTime(teachingBeginTime);
			teaching.setEndTime(teachingEndTime);

			teachings.add(teaching);
		}

		lessonService.modifyLesson(no, id, beginTime, endTime, name, classroom, courseType, teachings);

		setJson(JsonResultBuilder.success(true).msg("提交成功").json());

		return JSON;
	}

	@Operation(result = FILL)
	public String removeLesson() {
		String[] ids = form.readStrings("id");

		ArrayList<LessonRemoveReport> lessons = new ArrayList<LessonRemoveReport>();
		for (String id : ids) {
			Lesson lesson = lessonService.findOne(id);

			LessonRemoveReport lessonRemoveReport = new LessonRemoveReport();

			String msg;
			boolean success = false;

			long count = orderLessonService.countByLesson(id);
			if (count > 0) {
				msg = "已经被订课，不可删除";
			} else {
				try {
					lessonService.removeLesson(id);
					success = true;
					msg = "删除成功";
				} catch (Exception ex) {
					msg = "系统异常，删除失败，请稍后再试";
				}
			}

			lessonRemoveReport.setLesson(lesson);
			lessonRemoveReport.setMsg(msg);
			lessonRemoveReport.setSuccess(success);

			lessons.add(lessonRemoveReport);
		}

		put("lessons", lessons);

		return FILL;
	}

	@Operation(result = JSON)
	public String doRemoveLesson() {
		String id = form.readString("id");

		long count = orderLessonService.countByLesson(id);
		if (count > 0) {
			setJson(JsonResultBuilder.success(false).msg("不可删除的课程，该课已被学员订课，请先确认删除订课的学员").json());

			return JSON;
		}

		lessonService.removeLesson(id);

		setJson(JsonResultBuilder.success(true).msg("删除课程成功").json());

		return JSON;
	}

	@Operation(result = JSON)
	public String doCancelLesson() {
		String id = form.readString("id");

		lessonService.cancelLesson(id);

		setJson(JsonResultBuilder.success(true).msg("取消课程成功").json());

		return JSON;
	}

	@Operation(result = JSON)
	public String doResumeLesson() {
		String id = form.readString("id");

		lessonService.resumeLesson(id);

		setJson(JsonResultBuilder.success(true).msg("恢复课程成功").json());

		return JSON;
	}

	public TimePair getWeekTimePair(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);

		Date startDate = calendar.getTime();
		Date endDate = DateUtils.addDays(startDate, 7);

		TimePair timePair = new TimePair();
		timePair.setStartDate(startDate);
		timePair.setEndDate(endDate);

		return timePair;
	}

	@Operation(result = FILL)
	public String listLesson() {
		String[] teacherIds = form.readStrings("teacher");
		String[] canceleds = form.readStrings("canceled");

		LessonQuery lessonQuery = new LessonQuery();

		if (teacherIds.length > 0) {
			lessonQuery.setTeacherIds(teacherIds);
		}
		if (canceleds.length > 0) {
			boolean[] a = new boolean[canceleds.length];
			for (int i = 0; i < a.length; i++) {
				a[i] = "true".equals(canceleds[i]);
			}

			lessonQuery.setCanceleds(a);
		}

		// 开始上课时间
		Date startDate = valueReader.name("startDate").defaultValue(null).dateValue("yyyy-MM-dd");
		Date endDate = valueReader.name("endDate").defaultValue(null).dateValue("yyyy-MM-dd");
		if (startDate != null && endDate != null) {
			endDate = DateUtils.addDays(endDate, 1);

			TimePair timePair = new TimePair();
			timePair.setStartDate(startDate);
			timePair.setEndDate(endDate);

			lessonQuery.setDate(timePair);
		}

		Pageable paginations = getPageable(50);

		Page<Lesson> lessons = lessonService.findLesson(lessonQuery, paginations);
		put("lessons", lessons);

		put(PAGINATIONS, new Paginations(lessons));

		Iterable<User> teachers = teacherService.findAll();
		put("teachers", teachers);

		return FILL;
	}

	@Operation(result = FILL)
	public String listDailyLesson() {
		Date today = DateUtils.truncate(new Date(), Calendar.DATE);

		Date beginTime = valueReader.name("startDate").defaultValue(today).dateValue("yyyy-MM-dd");
		Date endTime = DateUtils.addDays(beginTime, 1);

		Iterable<Lesson> lessons = lessonService.findBetweenTime(beginTime, endTime);

		Date preTime = DateUtils.addDays(beginTime, -1);

		put("preDate", new SimpleDateFormat("yyyy-MM-dd").format(preTime));
		put("currentDate", new SimpleDateFormat("yyyy-MM-dd").format(beginTime));
		put("nextDate", new SimpleDateFormat("yyyy-MM-dd").format(endTime));
		put("lessons", lessons);

		TimePair timePair = getWeekTimePair(beginTime);

		put("startDate", new SimpleDateFormat("yyyy-MM-dd").format(timePair.getStartDate()));
		put("endDate", new SimpleDateFormat("yyyy-MM-dd").format(timePair.getEndDate()));

		return FILL;
	}

	@Operation(result = FILL)
	public String printDailyLesson() {
		Date today = DateUtils.truncate(new Date(), Calendar.DATE);

		Date beginTime = valueReader.name("startDate").defaultValue(today).dateValue("yyyy-MM-dd");
		Date endTime = DateUtils.addDays(beginTime, 1);

		Iterable<Lesson> lessons = lessonService.findBetweenTime(beginTime, endTime);

		put("currentDate", new SimpleDateFormat("yyyy-MM-dd").format(beginTime));
		put("lessons", lessons);

		return FILL;
	}

	public boolean hasForeign(Lesson lesson) {
		for (Teaching teaching : lesson.getTeachings()) {
			for (Role role : teaching.getTeacher().getRoles()) {
				if (role.getName().equals("外籍教师")) {
					return true;
				}
			}
		}

		return false;
	}

	@Operation(result = FILL)
	public String createLesson() {
		Iterable<User> teachers = teacherService.findAll();
		put("teachers", teachers);

		Iterable<Classroom> classrooms = classroomService.findAll();
		put("classrooms", classrooms);

		Iterable<CourseType> courseTypes = courseTypeService.findAll();
		put("courseTypes", courseTypes);

		return FILL;
	}

	@Operation(result = JSON)
	public String doCreateLesson() throws ParseException {
		String day = form.readString("date");
		String beginTimeStr = form.readString("beginTime");
		String endTimeStr = form.readString("endTime");

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");

		Date beginTime = simpleDateFormat.parse(day + " " + beginTimeStr);
		Date endTime = simpleDateFormat.parse(day + " " + endTimeStr);

		String name = form.readString("name");

		String[] teacherIds = form.readStrings("teacher");
		String[] teachingBeginTimes = form.readStrings("teachingBeginTime");
		String[] teachingEndTimes = form.readStrings("teachingEndTime");

		String classroom = form.readString("classroom");
		String courseType = form.readString("courseType");

		int no = valueReader.name("no").defaultValue(0).intValue();

		ArrayList<Teaching> teachings = new ArrayList<Teaching>();
		// 最后一个是界面误传不需要
		for (int i = 0; i < teacherIds.length - 1; i++) {
			Teaching teaching = new Teaching();

			User teacher = new User();
			teacher.setId(teacherIds[i]);

			teaching.setTeacher(teacher);

			Date teachingBeginTime = beginTime;

			try {
				String timeStr = teachingBeginTimes[i];
				if (StringUtils.isNotBlank(timeStr) && !"00:00".equals(timeStr)) {
					teachingBeginTime = simpleDateFormat.parse(day + " " + timeStr);
				}
			} catch (ParseException ex) {

			}

			Date teachingEndTime = endTime;
			try {
				String timeStr = teachingEndTimes[i];
				if (StringUtils.isNotBlank(timeStr) && !"00:00".equals(timeStr)) {
					teachingEndTime = simpleDateFormat.parse(day + " " + timeStr);
				}
			} catch (ParseException ex) {

			}

			teaching.setBeginTime(teachingBeginTime);
			teaching.setEndTime(teachingEndTime);

			teachings.add(teaching);
		}

		lessonService.createLesson(no, beginTime, endTime, name, classroom, courseType, teachings);

		setJson(JsonResultBuilder.success(true).msg("提交成功").json());

		return JSON;
	}

	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM.dd HH:mm:ss");

	@Autowired
	OrderLessonService orderLessonService;

	@Operation(result = FILL)
	public String listListener() {
		String id = form.readString("id");

		Lesson lesson = lessonService.findOne(id);
		put("lesson", lesson);

		Iterable<OrderLessonLog> logs = orderLessonService.findOrderLessonLogByLesson(id);
		put("logs", logs);

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String startDate = simpleDateFormat.format(lesson.getBeginTime());

		put("startDate", startDate);

		return FILL;
	}

	@Operation(result = FILL)
	public String reportLesson() {
		// 开始上课时间

		Date startDate = valueReader.name("startDate").defaultValue(null).dateValue("yyyy-MM-dd");
		Date endDate = valueReader.name("endDate").defaultValue(null).dateValue("yyyy-MM-dd");
		if (endDate != null) {
			endDate = DateUtils.addDays(endDate, 1);
		}
		TimePair timePair = new TimePair();
		timePair.setStartDate(startDate);
		timePair.setEndDate(endDate);

		List<TeacherBlankLessonReport> reports = lessonService.blankLessonReport();

		put("reports", reports);

		return FILL;
	}

	@Operation(result = JSON)
	public String doImportExcel() throws ParseException {

		String day = form.readString("day");
		String beginTime = form.readString("beginTime");
		String endTime = form.readString("endTime");

		int no = valueReader.name("no").defaultValue(0).intValue();
		if (StringUtils.isBlank(day) || StringUtils.isBlank(beginTime) || StringUtils.isBlank(endTime)) {

			setJson(JsonResultBuilder.success(false).msg("没有设置日期").json());

			return JSON;
		}

		String name = form.readString("name");
		String teachers = form.readString("teachers");
		String[] teacherIds = new String[0];
		if (teachers != null) {
			teacherIds = teachers.split(",");
		}
		String classroomId = form.readString("classroom");
		String courseTypeId = form.readString("courseType");

		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		Date beginDate = df.parse(day + " " + beginTime);
		Date endDate = df.parse(day + " " + endTime);

		lessonService.createLesson(no, beginDate, endDate, name, name, teacherIds, classroomId, courseTypeId);

		setJson(JsonResultBuilder.success(true).msg("成功").json());

		return JSON;
	}

	@Operation(result = FILL)
	public String importExcel() throws IOException, ParseException {
		form = RequestParameters.getForm();
		UploadFile uploadFile = form.readFile("excel");

		if (uploadFile == null) {
			return FILL;
		}

		ArrayList<Lesson> lessons = new ArrayList<Lesson>();

		BindException bindException = new BindException(lessons, "lessons");
		String campus = ((IeltsProfile) Profile.getInstance().getProfile()).getCampus();
		if (StringUtils.isBlank(campus)) {
			bindException.reject("000", "当前操作不属于任何校区，请选择一个校区后再操作。");

			put("bindException", bindException);
			return FILL;
		}

		DtoTable dtoTable;

		try {
			dtoTable = ExcelUtils.book(uploadFile.getFile()).sheet(0).addColumn(0, "day").addColumn(1, "time")
					.addColumn(2, "name").addColumn(3, "teahcings").addColumn(4, "classroom").parseToTable(0);
		} catch (Exception ex) {
			bindException.reject("000", "导入Excel失败，错误信息:" + ex.getMessage() + ",请检查你的Excel是否符合格式标准");

			put("bindException", bindException);
			return FILL;
		}

		ArrayList<BindException> bindExceptions = new ArrayList<BindException>();
		initClassrooms();
		initTeachers();
		put("teachers", teachers);
		put("classrooms", classrooms);

		// 准备导入
		int i = 0;
		String day = null;
		for (IDtoRow iDtoRow : dtoTable) {
			Lesson lesson = new Lesson();
			BindException lessonBindException = new BindException(lesson, "lesson");
			i++;

			Date beginTime = null;
			Date endTime = null;

			try {
				String newDay = (String) iDtoRow.get("day");
				if (StringUtils.isNotBlank(newDay)) {
					day = newDay;
				}
				String time = (String) iDtoRow.get("time");
				if (time == null) {
					lessonBindException.rejectValue("beginTime", "100", "获得时间错误");
				} else {
					String[] times = StringUtils.split(time, "-");
					Day dayInfo = ParseUtils.parseDay(day);
					Time beginTimeInfo = ParseUtils.parseTime(times[0]);
					Time endTimeInfo = ParseUtils.parseTime(times[1]);

					beginTime = ParseUtils.buildDate(dayInfo, beginTimeInfo);
					endTime = ParseUtils.buildDate(dayInfo, endTimeInfo);
				}
			} catch (Exception ex) {
				lessonBindException.rejectValue("beginTime", "100", "获得时间错误");
			}

			lesson.setBeginTime(beginTime);
			lesson.setEndTime(endTime);

			String classroomName = (String) iDtoRow.get("classroom");
			Classroom classroom = null;

			classroom = classroomMap.get(classroomName);
			if (classroom == null) {
				lessonBindException.rejectValue("classroom", "102", "本校区未找到名为：" + classroomName + "的教室");
			}

			lesson.setClassroom(classroom);

			String teacherName = (String) iDtoRow.get("teahcings");
			String[] teacherNames = StringUtils.split(teacherName);
			if (teacherNames != null) {
				for (String n : teacherNames) {
					if (StringUtils.isNotBlank(n)) {

						List<User> users = nameTeachers.get(n);
						if (users == null || users.size() == 0) {
							User user = loginTeachers.get(n);
							if (user == null) {
								user = noTeachers.get(n);
							}
							if (user == null) {
								lessonBindException.rejectValue("teachings", "103", "未找名为：" + n + "的教师");
							} else {
								Teaching teaching = new Teaching();
								teaching.setTeacher(users.get(0));
								lesson.getTeachings().add(teaching);
							}
						} else if (users.size() == 1) {
							Teaching teaching = new Teaching();
							teaching.setTeacher(users.get(0));
							lesson.getTeachings().add(teaching);
						} else {
							User user = loginTeachers.get(n);
							if (user == null) {
								user = noTeachers.get(n);
							}
							if (user == null) {
								lessonBindException.rejectValue("teachings", "103", "名为：" + n + "的教师不止一个");
							} else {
								Teaching teaching = new Teaching();
								teaching.setTeacher(users.get(0));
								lesson.getTeachings().add(teaching);
							}
						}
					}
				}
			} else if (teacherNames == null || teacherNames.length == 0) {
				lessonBindException.rejectValue("teachings", "104", "没有设置教师");
			}

			String name = (String) iDtoRow.get("name");
			if (StringUtils.isBlank(name)) {
				lessonBindException.rejectValue("name", "105", "课程名称还未设置");
			}

			lesson.setName(name);

			lessons.add(lesson);

			bindExceptions.add(lessonBindException);
		}

		put("bindExceptions", bindExceptions);
		put("lessons", lessons);

		Iterable<CourseType> courseTypes = courseTypeService.findAll();
		put("courseTypes", courseTypes);
		
		return FILL;
	}

	Map<String, Classroom> classroomMap;
	Iterable<Classroom> classrooms;

	private void initClassrooms() {
		classroomMap = new HashMap<String, Classroom>();
		classrooms = classroomService.findAll();
		for (Classroom classroom : classrooms) {
			classroomMap.put(classroom.getName(), classroom);
		}
	}

	Map<String, User> loginTeachers;
	Map<String, List<User>> nameTeachers;
	Map<String, User> noTeachers;
	Iterable<User> teachers;

	private void initTeachers() {
		loginTeachers = new HashMap<String, User>();
		nameTeachers = new HashMap<String, List<User>>();
		noTeachers = new HashMap<String, User>();

		teachers = teacherService.findAll();

		for (User user : teachers) {
			loginTeachers.put(user.getLoginName(), user);
			if (user.getNo() != null) {
				noTeachers.put(user.getNo(), user);
			}

			List<User> users = nameTeachers.get(user.getName());
			if (users == null) {
				users = new ArrayList<User>();
				users.add(user);

				nameTeachers.put(user.getName(), users);
			} else {
				users.add(user);
			}
		}
	}

	@Autowired
	UserService userService;
}
